<!DOCTYPE html>
<html>
<head>
	<title>Document Visualisation</title>
	<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
	<script src="lib/cytoscape.js"></script>
	<script src="lib/arbor.js"></script>
	<script src="lib/brat-linked-vis.js"></script>
</head>

<body>
	<h1>Waiting to select graph...</h1>
	<div id="demo" style="width: 100%; height: 500px;"></div>

	<div id="graph-details">
		<!--<label for="user">User ID</label><input type="text" id="user" name="user" value="flawrence" />
		<label for="document">Document</label><input type="text" id="document" name="document" value="RRHS25-S17" />
		<button id="update_graph">Update Graph</button>-->
		<label for="document_list">Document</label><select id="document_list" name="document_list"></select>
		<button id="refresh_document_list">Refresh</button>
	</div>

	<script>

	options = {
    name: 'arbor',

    liveUpdate: true, // whether to show the layout as it's running
    ready: undefined, // callback on layoutready
    stop: undefined, // callback on layoutstop
    maxSimulationTime: 4000, // max length in ms to run the layout
    fit: true, // reset viewport to fit default simulationBounds
    padding: [ 50, 50, 50, 50 ], // top, right, bottom, left
    simulationBounds: undefined, // [x1, y1, x2, y2]; [0, 0, width, height] by default
    ungrabifyWhileSimulating: true, // so you can't drag nodes during layout

    // forces used by arbor (use arbor default on undefined)
    repulsion: undefined,
    stiffness: undefined,
    friction: undefined,
    gravity: true,
    fps: undefined,
    precision: undefined,

    // static numbers or functions that dynamically return what these
    // values should be for each element
    nodeMass: undefined,
    edgeLength: undefined,

    stepSize: 1, // size of timestep in simulation

    // function that returns true if the system is stable to indicate
    // that the layout can be stopped
    stableEnergy: function( energy ){
      var e = energy;
      return (e.max <= 0.5) || (e.mean <= 0.3);
    }
};

// Edit this array to contain all the links you want to search for on this graph
	var required_links = [
		'http://contextus.net/ontology/ontomedia/core/expression#has-subject-entity',
		'http://contextus.net/ontology/ontomedia/core/expression#has-object-entity',
		'http://contextus.net/ontology/ontomedia/core/expression#to',
		'http://contextus.net/ontology/ontomedia/core/expression#from',
		'http://contextus.net/ontology/ontomedia/ext/events/social#has-subject',
	];

// Edit this array to contain cytoscape style objects for each link and node type
	var styles = {
		'http://contextus.net/ontology/ontomedia/core/expression#has-subject-entity':
		{
			'name': 'has-subject-entity',
			'type': 'edge',
			'css': { 'width': 2, 'target-arrow-shape': 'triangle', 'target-arrow-color': 'black', 'line-color': 'black', 'content': 'has-subject-entity' }
		},
		'http://contextus.net/ontology/ontomedia/core/expression#has-object-entity':
		{
			'name': 'has-object-entity',
			'type': 'edge',
		 	'css': { 'width': 2, 'target-arrow-shape': 'triangle', 'target-arrow-color': 'black', 'line-color': 'black', 'content': 'has-object-entity' }
		},
		'http://contextus.net/ontology/ontomedia/core/expression#to':
		{
			'name': 'to',
			'type': 'edge',
		 	'css': { 'width': 2, 'target-arrow-shape': 'triangle', 'target-arrow-color': 'yellow', 'line-color': 'yellow', 'content': 'to' }
		},
		'http://contextus.net/ontology/ontomedia/core/expression#from':
		{
			'name': 'from',
			'type': 'edge',
			'css': { 'width': 2, 'target-arrow-shape': 'triangle', 'target-arrow-color': 'yellow', 'line-color': 'yellow', 'content': 'from' }
		},
		'http://contextus.net/ontology/ontomedia/ext/events/social#has-subject':
		{
			'name': 'has-subject',
			'type': 'edge',
			'css': { 'width': 2, 'target-arrow-shape': 'triangle', 'target-arrow-color': 'red', 'line-color': 'red', 'content': 'has-subject' }
		},
		'http://contextus.net/ontology/ontomedia/core/expression#Character':
		{
			'name': 'character',
			'type': 'node',
			'css': { 'background-fit': 'cover', 'background-image': 'lib/assets/icons_character.png', 'background-color': 'yellow', 'radius' : 10, 'content': 'data(name)' }
		},
		'http://contextus.net/ontology/ontomedia/core/expression#Space':
		{
			'name': 'space',
			'type': 'node',
			'css': { 'background-fit': 'cover', 'background-image': 'lib/assets/icons_space.png', 'background-color': 'yellow', 'radius' : 10, 'content': 'data(name)' }
		}
	};

// Edit this array to contain cytoscape styles for anything not covered by the above classes
	var default_node = { 'content': 'data(name)', 'background-color': 'green', 'shape': 'circle', 'width' : 20 };
	var default_edge = { 'content': 'data(label)', 'background-color': 'green', 'width' : 3 };

// Edit this array to contain the query string, with __GRAPH__ and __LINK_TYPE__ as placeholders
	var query_string = 'PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \
		PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \
		\
		SELECT  DISTINCT * WHERE {GRAPH <__GRAPH__> \
		{ \
		\
		?subj <__LINK_TYPE__> ?obj; \
			rdf:type ?subj_type . \
		\
		OPTIONAL {?subj rdfs:label ?subj_label }. \
		OPTIONAL {?subj <http://www.w3.org/2011/content#chars> ?subj_text }. \
		OPTIONAL {?subj <http://contextus.net/ontology/ontomedia/ext/common/trait#has-trait> [rdf:type <http://contextus.net/ontology/ontomedia/ext/common/trait#Name>; \
		<http://contextus.net/ontology/ontomedia/ext/common/trait#has-name> ?subj_name]}. \
		OPTIONAL {?subj <http://www.w3.org/2002/07/owl#sameAs> ?local_subj. \
		?local_subj <http://contextus.net/ontology/ontomedia/core/expression#shadow-of> ?global_subj. \
		?global_subj rdfs:label ?global_subj_label} \
		\
		?obj rdf:type ?obj_type . \
		OPTIONAL {?obj rdfs:label ?obj_label }. \
		OPTIONAL {?obj <http://www.w3.org/2011/content#chars> ?obj_text }. \
		OPTIONAL {?obj <http://contextus.net/ontology/ontomedia/ext/common/trait#has-trait> [rdf:type <http://contextus.net/ontology/ontomedia/ext/common/trait#Name>; \
		<http://contextus.net/ontology/ontomedia/ext/common/trait#has-name> ?obj_name]}. \
		OPTIONAL {?obj <http://www.w3.org/2002/07/owl#sameAs> ?local_obj. \
		?local_obj <http://contextus.net/ontology/ontomedia/core/expression#shadow-of> ?global_obj. \
		?global_obj rdfs:label ?global_obj_label} \
		} \
		}';

// Edit this to point to your public SPARQL endpoint
sparql_root = 'http://brat.kludge.co.uk/sparql/';

// Don't edit anything past here
	var matchEventRegex = /E\d+/;
	var chart = null;
	var graph_url;
	var data;

	$( document ).ready(function() {
		if (chart == null)
		{
            chart = cytoscape({
                container: document.getElementById('demo'),
            });
 		}

		$('#update_graph').click(function() {
			update_graph();
		});

		$('#document_list').change(function () {
			update_graph();
		});

		$('#refresh_document_list').click(function() {
			refresh_document_list(sparql_root);
		});
	    refresh_document_list(sparql_root);
	});

	function refresh_page()
	{
	    update_graph();
	}

	function update_graph ( )
	{
//		graph_url = graph_base_url + $('#user').val() + '/' + $('#document').val();
		$("h1").text("Document graph for " + $('#document_list option:selected').text());
		graph_url = $('#document_list').val();
	    data = { "nodes": [], "edges":[] };
		prepareData(0);
	}

    function prepareData ( link_index )
    {
    	if (link_index >= required_links.length)
    	{
            chart = cytoscape({
                container: document.getElementById('demo')
            });

    		chart.style().selector('edge').css(default_edge);
    		chart.style().selector('node').css(default_node);
    		$.each(styles, function (style_match, style_details)
    		 {
    		 	selector = style_details['type'] + '.' + style_details['name'];
    		 	chart.style().selector(selector).css(style_details['css']);
    		 });
    		chart.add(data);
    		chart.layout(options);

    		return;
    	}

		$.ajax({
    		url: sparql_root,
    		dataType: 'json',
		    data: {
        		query: query_string.replace('__GRAPH__', graph_url).replace('__LINK_TYPE__', required_links[link_index]),
		    },

		    success: function( response ) {

		    	// Find all the individual nodes first


		    	$.each(response.results.bindings, function (index, triple) {
		    		var subj_id = triple.subj.value;
		    		var subj_type = triple.subj_type.value;
		    		var subj_label = subj_id;
		    		//if ('value' in triple.subj_text) subj_label = triple.subj_text.value;
		    		if ('value' in triple.subj_label) subj_label = triple.subj_label.value;
		    		if ('value' in triple.subj_name) subj_label = triple.subj_name.value;
					if ('value' in triple.global_subj) subj_id = triple.global_subj.value;
					if ('value' in triple.global_subj_label) subj_label = triple.global_subj_label.value;
					if (matchEventRegex.test(subj_label))
					{
					 	subj_label = subj_type.split("#")[1];
					}

		    		var obj_id = triple.obj.value;
		    		var obj_type = triple.obj_type.value;
		    		var obj_label = obj_id;
		    		//if ('value' in triple.obj_text) obj_label = triple.obj_text.value;
		    		if ('value' in triple.obj_label) obj_label = triple.obj_label.value;
		    		if ('value' in triple.obj_name) obj_label = triple.obj_name.value;
					if ('value' in triple.global_obj) obj_id = triple.global_obj.value;
					if ('value' in triple.global_obj_label) obj_label = triple.global_obj_label.value;
					if (matchEventRegex.test(obj_label))
					{
						obj_label = obj_type.split("#")[1];
					}

		    		var foundS = 0;
		    		var foundO = 0;


		    		for (i = 0; i < data['nodes'].length; i++)
		    		{
		    			if (data['nodes'][i]['id'] == subj_id) foundS = 1;
		    			if (data['nodes'][i]['id'] == obj_id) foundO = 1;
		    		}
/*
		    		var subj_style = $.extend({'label': subj_label}, (styles[subj_type] == undefined) ? default_style : styles[subj_type]);
					var obj_style = $.extend({'label': obj_label}, (styles[obj_type] == undefined) ? default_style : styles[obj_type]);

		    		if (foundS == 0) data['nodes'].push({'id': subj_id, 'style': subj_style});
		    		if (foundO == 0) data['nodes'].push({'id': obj_id, 'style': obj_style});

		    		*/

		    		if (foundS == 0)
		    		{
		    			if (styles[subj_type] != undefined)
		    				data['nodes'].push({'data': {'id': subj_id, 'name': subj_label}, 'classes': styles[subj_type]['name']});
		    			else
		    				data['nodes'].push({'data': {'id': subj_id, 'name': subj_label}});
		    		}

		    		if (foundO == 0)
	    			{
		    			if (styles[obj_type] != undefined)
		    				data['nodes'].push({'data': {'id': obj_id, 'name': obj_label}, 'classes': styles[obj_type]['name']});
		    			else
		    				data['nodes'].push({'data': {'id': obj_id, 'name': obj_label}});
	    			}

		    	});

		    	$.each(response.results.bindings, function (index, triple) {
		    		var subj_id = triple.subj.value;
					if ('value' in triple.global_subj) subj_id = triple.global_subj.value;

		    		var obj_id = triple.obj.value;
					if ('value' in triple.global_obj) obj_id = triple.global_obj.value;

		    		//data['links'].push({"id": required_links[link_index] + "_link" +  index.toString(), "from": subj_id, "to": obj_id, style: styles[required_links[link_index]]});

		    		var to_add = true;

		    		$.each(data['edges'], function(index, existing)
		    		{
		    		   if(existing['data'].label == required_links[link_index].split('#')[1] && existing['data'].source == subj_id && existing['data'].target == obj_id)
		    		   {
		    		        to_add = false;
		    		   }

		    		});


		    		if(to_add)
		    		{
		    			if (styles[required_links[link_index]] != undefined)
		    		    	data['edges'].push({'data':{"id": required_links[link_index] + "_link" +  index.toString(), "source": subj_id, "target": obj_id, 'label': required_links[link_index].split('#')[1]}, 'classes': styles[required_links[link_index]]['name']});
		    			else
		    		    	data['edges'].push({'data':{"id": required_links[link_index] + "_link" +  index.toString(), "source": subj_id, "target": obj_id, 'label': required_links[link_index].split('#')[1]}});
                    }

		    	});

	    		prepareData(link_index+1);
    		}
		});

    }




</script>
</body>
</html>